import React from "react";
import {renderIcon, VJsonComponent} from "../../factory";
import {ComplexArrayResult, DataComponentProp, DataComponentState, VJsonDataComponentBase} from "../../datasource";
import {Table as AntTable, Pagination as AntdPagination, Input, Space, Button} from "antd";
import _ from "lodash";
import {YvanEvent} from "../../types";
import {SizeType} from "antd/es/config-provider/SizeContext";
import {ApiObject, ApiResult} from "../../ajax";
import {toJS} from "mobx";
import {applyValue, YvanEventDispatch} from "../..";
import {Resizable} from 'react-resizable';
import * as Extend from '../../extend'
import any = jasmine.any;
import {SearchOutlined} from '@ant-design/icons'

// import Highlighter from 'react-highlight-words';

export interface TableVJsonDataProp extends DataComponentProp<Table> {
    /**
     * 是否可见
     */
    visible?: boolean
    tableLayout?: 'auto' | 'fixed'
    bordered?: boolean
    columns?: any //ColumnsType<any>[]
    emptyText?: string
    rowClassName?: string
    showHeader?: boolean
    size?: SizeType
    paginationOption?: any
    pagination?: boolean
    onCheckedChange: (sender: Table, checkedRowKeys: any[], checkedRowData: any) => void
}

export interface TableState extends DataComponentState {
    pageSize: number
    currentPage: number
    total: number
    checkedRowKeys: any[]
    checkedRowData: any[]
    selectedRowKey: any
    selectedRowData: any
    columns: any[]
    sortModel: any[]
    filterModel: any
    searchText: any
    searchedColumn: any
}

@VJsonComponent({
    view: 'table'
})
export default class Table extends VJsonDataComponentBase<Table, TableVJsonDataProp, TableState> {
    static defaultProps = {
        ...VJsonDataComponentBase.defaultProps,
        columns: [],
        idField: "_defaultRowKey_",
        size: 'small',
        bordered: true,
        visible: true,
        paginationOption: {
            showSizeChanger: true,
            showQuickJumper: true,
            showTotal: (total: number) => `总共 ${total} 条`
        }
    }

    constructor(props: any) {
        super(props);

        const me = this;
        _.defaults(
            props.vjson,
            Table.defaultProps
        )

        // 换掉了基类的 onDataSourceAfter 方法，替换为 dataSourceAfterSuper
        this.dataSourceAfterSuper = this.onDataSourceAfter
        this.onDataSourceAfter = this.dataSourceAfter

        const cols: any[] = toJS(this.props.vjson.columns);
        // 添加行号
        if (!this.props.vjson.hidRowNumber) {
            const cc = {
                title: "序号",
                render(text: string, value: any, record: any, index: number) {
                    const rowNumber = (me.state.currentPage - 1) * me.state.pageSize + index + 1;
                    // me.data[index]._defaultRowKey_ = rowNumber;
                    return (
                        <span>{rowNumber}</span>
                    )
                },
                // fixed: true
            }
            if (cols.length === 0) {
                cols.push(cc)
            } else {
                cols.splice(0, 0, cc)
            }
        }

        // 强制单元格不换行
        // for (let i = 0; i < cols.length; i++) {
        //     // 强制单元格不换行
        //     cols[i]["ellipsis"] = true;
        //     cols[i].onHeaderCell = (column: any) => ({
        //         width: column.width,
        //         onResize: this.handleResize(i),
        //     })
        //     cols[i].width = cols[i].width ? cols[i].width : 100;
        //
        //     // 处理格式化
        //     // const customRender = cols[i]["render"];
        //     // const formatter = cols[i]["formatter"];
        //     // if (typeof formatter === "string") {
        //     //     cols[i].render = function (value: any, rowData: any, index: number) {
        //     //         const re = Extend.formatter[formatter](value);
        //     //         if (typeof customRender === "function") {
        //     //             return customRender(value, re, rowData, index);
        //     //         }
        //     //         return re;
        //     //     }
        //     // } else if (formatter instanceof Array) {
        //     //     cols[i].render = function (value: any, rowData: any, index: number) {
        //     //         let re = value;
        //     //         for (let n = 0; n < formatter.length; n++) {
        //     //             if (formatter[n].id == value) {
        //     //                 re = formatter[n].text
        //     //                 break
        //     //             }
        //     //         }
        //     //         if (typeof customRender === "function") {
        //     //             return customRender(value, re, rowData, index);
        //     //         }
        //     //         return re;
        //     //     }
        //     // } else {
        //     //     cols[i].render = function (value: any, rowData: any, index: number) {
        //     //         if (typeof customRender === "function") {
        //     //             return customRender(value, value, rowData, index);
        //     //         }
        //     //         return value;
        //     //     }
        //     // }
        //     _.assign(cols[i], this.getColumnSearchProps(cols[i].dataIndex));
        // }

        this.state = {
            ...this.state,
            columns: cols,
            sortModel: [],
            pageSize: props.vjson.pageSize,
        }
    }

    private readonly dataSourceAfterSuper?: (sender: Table, dataOrgin: any[], responseRaw: any, api: ApiObject) => ComplexArrayResult<any>

    /**
     * 拿到原始的请求结果之后，需要进行下一步处理
     */
    private dataSourceAfter(sender: Table, dataOrgin: any[], responseRaw: any, api: ApiObject): ComplexArrayResult<any> {
        const dataSourceAfterSuper = this.dataSourceAfterSuper || ((_, v: any) => v)

        const me = this
        // 换掉了基类的 onDataSourceAfter 方法，要重新调用回来
        return new Promise(resolve => {
            applyValue(dataSourceAfterSuper.call(this, sender, dataOrgin, responseRaw, api)).then(res => {

                if (this.props.vjson.pagination) {
                    if (typeof res.pagination === 'object') {
                        // 从 res 中能获取到 pagination
                        sender.setState({
                            currentPage: parseInt(res.pagination.current),
                            total: (parseInt(res.pagination.total) === 0 ? sender.state.total : parseInt(res.pagination.total)),
                            pageSize: parseInt(res.pagination.size)
                        })
                        // @ts-ignore
                        resolve(res.data)

                    } else {
                        // 处理分页数据
                        sender.setState({
                            currentPage: parseInt(responseRaw.pagination.current),
                            total: (parseInt(responseRaw.pagination.total) === 0 ? sender.state.total : parseInt(responseRaw.pagination.total)),
                            pageSize: parseInt(responseRaw.pagination.size)
                        })

                        // @ts-ignore
                        resolve(res)
                    }
                }
            })
        })
    }

    componentDidMount() {
        super.componentDidMount();
        if (!this.props.vjson.pagination) {
            this.setState({currentPage: 1, pageSize: 0});
            return
        }
        if (this.props.vjson.defaultPage && this.props.vjson.defaultPage > 0) {
            this.setState({currentPage: this.props.vjson.defaultPage});
        } else {
            this.setState({currentPage: 1});
        }
    }

    get data() {
        if (this.dataBind) {
            return _.get(this.props.$context.scopeInstance, this.dataBind + '.data')
        }
        // @ts-ignore
        return this.state.data
    }

    set data(value: any[]) {

        // 添加表格id列
        for (let i = 0; i < value.length; i++) {
            value[i]["_defaultRowKey_"] = (this.state.currentPage - 1) * this.state.pageSize + i + 1;
        }

        if (this.dataBind) {
            _.set(this.props.$context.scopeInstance, this.dataBind + '.data', value)
        } else {
            this.setState({
                // @ts-ignore
                data: value
            })
        }
    }

    /**
     * 自定义 serverJS Data 参数
     */
    protected serverJsParamsParser(apiObject: ApiObject): Promise<ApiObject> {
        return new Promise(resolve => {
            const pageOption: any = {}
            if (this.props.vjson.pagination) {
                let pageSize = this.props.vjson.pageSize;
                if (this.state.pageSize > 0) {
                    pageSize = this.state.pageSize;
                }
                let currentPage = 0;
                if (this.state.currentPage > 0) {
                    currentPage = this.state.currentPage - 1;
                }

                // 需要分页
                _.assign(pageOption, {
                    limit: pageSize,
                    limitOffset: currentPage * pageSize,
                    // 如果强制要求每次获取总数， 就每次获取当前总数， 否则只在加载默认页面的时候获取总数
                    needCount: this.props.vjson.requiredCount === true ? true : this.state.currentPage === 1 || this.state.currentPage === this.props.vjson.defaultPage,
                })
            }


            // @ts-ignore
            if (apiObject.method === 'server') {
                // 表格的标准请求为：
                //      filterModel: {}
                //      limit: 100
                //      limitOffset: 0
                //      needCount: true
                //      params: {…}
                //      sortModel: []

                const params = apiObject.data
                apiObject.data = {
                    filterModel: this.state.filterModel,
                    params,
                    sortModel: this.state.sortModel
                }

                // console.log('业务代码写在这里', apiObject.data)
                _.assign(apiObject.data, pageOption)

            } else {
                // 自主性 ajax 只是添加一个 pagination 属性
                _.set(apiObject, 'data.pagination', pageOption)
            }

            resolve(apiObject)
        })
    }

    /**=========================== 表格分页相关 ======================== **/

    onPageChange(currentPage: number, pageSize?: number) {
        if (pageSize && this.state.pageSize !== pageSize) {
            this.setState({pageSize});
            this.setState({currentPage: 1});
        } else {
            this.setState({currentPage});
        }
        this.refresh();
    }

    renderPagination() {
        if (!this.props.vjson.pagination) {
            return null
        }
        return (
            <AntdPagination
                total={this.state.total}
                defaultPageSize={this.props.vjson.pageSize}
                // onShowSizeChange={this.onShowSizeChange.bind(this)}
                current={this.state.currentPage}
                onChange={this.onPageChange.bind(this)}
                {
                    ...this.props.vjson.paginationOption
                }
            />
        )
    }

    /**=========================== 表格勾选相关 ======================== **/

    public getCheckedData(): any[] {
        return this.state.checkedRowData;
    }

    private onSelectChange(checkedRowKeys: any[], checkedRowData: any) {
        this.setState({checkedRowKeys, checkedRowData})
        YvanEventDispatch(this.props.vjson.onCheckedChange, this, checkedRowKeys, checkedRowData)
    };

    /**=========================== 表格行选中 ======================== **/

    public getSelectedData(): any {
        return this.state.selectedRowData;
    }

    private onClickRow(record: any) {
        return {
            onClick: () => {
                this.setState({
                    selectedRowKey: record[this.props.vjson.idField],
                    selectedRowData: record,
                });
            },
        };
    }

    private setRowClassName(record: any) {
        const clickRowStyle = this.props.vjson.clickRowStyle ? this.props.vjson.clickRowStyle : 'clickRowStyle'
        const rowDefaultStyle = this.props.vjson.rowDefaultStyle ? this.props.vjson.rowDefaultStyle : ''
        return record[this.props.vjson.idField] === this.state.selectedRowKey ? clickRowStyle : rowDefaultStyle;
    }

    /**=========================== 表格调整列宽 ======================== **/

    private handleResize(index: number) {
        return (e: any, param: any) => {
            this.setState(function ({columns}) {
                const nextColumns = [...columns];
                nextColumns[index] = {
                    ...nextColumns[index],
                    width: param.size.width,
                };
                return {columns: nextColumns};
            });
        }
    }

    /**=========================== 表格筛选排序 ======================== **/

    private handleTableChange(pagination: any, filters: any, sorter: any) {
        const order = sorter.order === "descend" ? "desc" : sorter.order === "ascend" ? "asc" : "";
        let find = false;
        for (let i = this.state.sortModel.length - 1; i >= 0; i--) {
            const el = this.state.sortModel[i];
            if (el.colId === sorter.field) {
                if (order.length > 0) {
                    el.sort = order;
                } else {
                    this.state.sortModel.splice(i, 1);
                }
                find = true;
                break
            }
        }
        if (!find && order.length > 0) {
            this.state.sortModel.push({
                colId: sorter.field,
                sort: order
            })
        }
        this.refresh()
    };


    private getColumnSearchProps(dataIndex: string) {

        const me = this
        return {
            filterDropdown: function ({setSelectedKeys, selectedKeys, confirm, clearFilters}: any) {
                return (
                    <div style={{padding: 8}}>
                        <Input
                            ref={node => {
                                // me.searchInput = node;
                            }}
                            placeholder={`Search ${dataIndex}`}
                            value={selectedKeys[0]}
                            onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
                            onPressEnter={() => me.handleSearch(selectedKeys, confirm, dataIndex)}
                            style={{width: 188, marginBottom: 8, display: 'block'}}
                        />
                        <Space>
                            <Button
                                type="primary"
                                onClick={() => me.handleSearch(selectedKeys, confirm, dataIndex)}
                                icon={<SearchOutlined/>}
                                size="small"
                                style={{width: 90}}
                            >
                                Search
                            </Button>
                            <Button onClick={() => me.handleReset(clearFilters)} size="small" style={{width: 90}}>
                                Reset
                            </Button>
                        </Space>
                    </div>
                )
            },
            filterIcon: function (filtered: any) {
                return (<SearchOutlined style={{color: filtered ? '#1890ff' : undefined}}/>)
            },
            onFilter: function (value: any, record: any) {
                return record[dataIndex]
                    ? record[dataIndex].toString().toLowerCase().includes(value.toLowerCase())
                    : ''
            },
            onFilterDropdownVisibleChange: function (visible: any) {
                if (visible) {
                    // setTimeout(() => me.searchInput.select(), 100);
                }
            },
            render: function (text: string) {
                return text
                // me.state.searchedColumn === dataIndex ? (
                //     <Highlighter
                //         highlightStyle={{ backgroundColor: '#ffc069', padding: 0 }}
                //         searchWords={[me.state.searchText]}
                //         autoEscape
                //         textToHighlight={text ? text.toString() : ''}
                //     />
                // ) : (
                //     text
                // )
            }
        }
    }


    private handleSearch(selectedKeys: any, confirm: any, dataIndex: any) {
        confirm();
        this.setState({
            searchText: selectedKeys[0],
            searchedColumn: dataIndex,
        });
    }

    private handleReset(clearFilters: any) {
        clearFilters();
        this.setState({searchText: ''});
    }


    render() {
        if (!this.props.vjson.visible) {
            return null
        }
        const components = {
            header: {
                cell: ResizableTitle,
            },
        };

        return (
            // @ts-ignore
            <div key={this.key} view_id={this.key} aria-roledescription={this.view}>
                <AntTable
                    scroll={{x: 1, y: this.props.vjson.height}}
                    // components={components}
                    dataSource={this.data}
                    tableLayout={this.props.vjson.tableLayout}
                    bordered={this.props.vjson.bordered}
                    columns={this.state.columns}
                    loading={this.loading}
                    pagination={false}
                    style={toJS(this.props.vjson.style)}
                    // rowClassName={this.props.vjson.rowClassName}
                    rowKey={this.props.vjson.idField}
                    showHeader={this.props.vjson.showHeader}
                    size={this.props.vjson.size}

                    rowSelection={
                        this.props.vjson.selection === true ?
                            {
                                type: 'checkbox',
                                selectedRowKeys: this.state.checkedRowKeys,
                                onChange: this.onSelectChange.bind(this),
                            } :
                            undefined
                    }
                    onRow={this.onClickRow.bind(this)}
                    rowClassName={this.setRowClassName.bind(this)}
                    onChange={this.handleTableChange.bind(this)}
                />
                {
                    this.renderPagination()
                }
            </div>
        )
    }
}

/**=========================== 表格列宽调整handel ======================== **/

const ResizableTitle = (props: any) => {
    const {onResize, width, ...restProps} = props;

    if (!width) {
        return <th {...restProps} />;
    }
    return (
        <Resizable
            width={width}
            height={0}
            handle={
                <span
                    className="react-resizable-handle"
                    onClick={e => {
                        e.stopPropagation();
                    }}
                />
            }
            onResize={onResize}
            draggableOpts={{enableUserSelectHack: false}}
        >
            <th {...restProps} />
        </Resizable>
    );
};